#ifndef pix_First
#define pix_First
#ifdef __GNUG__
#pragma interface
#endif

#include "ET_stdio.h"

typedef char *caddr_t;

#ifndef coord
#define coord   short
#endif

struct colormap_t {
		int              type;
		int              length;
		unsigned char   *map[3];
};

struct rect {
		coord   r_left, r_top;
		short   r_width, r_height;
};

#define rect_intersectsrect(r1,r2) \
		((r1)->r_left<(r2)->r_left+(r2)->r_width && \
		(r1)->r_top<(r2)->r_top+(r2)->r_height &&  \
		(r2)->r_left<(r1)->r_left+(r1)->r_width && \
		(r2)->r_top<(r1)->r_top+(r1)->r_height)

extern struct rectlist rl_null;

struct  rectnode {
		struct  rectnode *rn_next;
		struct  rect rn_rect;
};

struct  rectlist {
		coord   rl_x, rl_y;
		struct  rectnode *rl_head;
		struct  rectnode *rl_tail;
		struct  rect rl_bound;
};

struct pr_size {
		int     x, y;
};

struct pr_pos {
		int     x, y;
};

struct pixrect {
		struct  pixrectops *pr_ops;
		struct  pr_size pr_size;
		int     pr_depth;
		struct mpr_data *pr_data;
};

struct mpr_data {
		int     md_linebytes;   /* number of bytes from one line to next */
		short   *md_image;      /* word address */
		struct  pr_pos md_offset;
		short   md_primary;
		short   md_flags;       /* Flag bits, see below */
};

struct pixrectops {
		int     (*pro_rop)( ... );
		int     (*pro_stencil)( ... );
		int     (*pro_batchrop)( ... );
		int     (*pro_nop)( ... );
		int     (*pro_destroy)( ... );
		int     (*pro_get)( ... );
		int     (*pro_put)( ... );
		int     (*pro_vector)( ... );
		struct pixrect* (*pro_region)( ... );
		int     (*pro_putcolormap)( ... );
		int     (*pro_getcolormap)( ... );
		int     (*pro_putattributes)( ... );
		int     (*pro_getattributes)( ... );
};

struct pr_chain {
		struct pr_chain *next;
		struct pr_size  size;
		int             *bits;
};

struct pr_fall {
		struct pr_pos   pos;
		struct pr_chain *chain;
};

struct pr_trap {
		struct pr_fall  *left, *right;
		int y0, y1;
};

struct pr_prpos {
	struct pixrect *pr;
	struct  pr_pos pos;
};

struct pixchar {
	struct pixrect *pc_pr;
	struct pr_pos pc_home;
	struct pr_pos pc_adv;
};

typedef struct pixfont {
	struct pr_size pf_defaultsize;
	struct pixchar pf_char[256];
} Pixfont;

#define PWCD_SET_CMAP_SIZE      0x40
#define PIX_MAX_PLANE_GROUPS    12
#define RECTS_SORTS             4
#define BITSPERBYTE             8
#define VKEY_KBD_CODES          128
#define VKEY_CODES              VKEY_KBD_CODES

#define IM_CODEARRAYSIZE        (VKEY_CODES/((sizeof(char))*BITSPERBYTE))
#define IM_SHIFTARRAYSIZE       (sizeof(short)*BITSPERBYTE)

#define IE_NEGEVENT     (0x01)
#define SHIFTMASK       0x000E
#define CTRLMASK        0x0030
#define META_SHIFT_MASK 0x0040

#define WL_ENCLOSING    0
#define WL_COVERED      1
#define WL_COVERING     2
#define WL_BOTTOMCHILD  3
#define WL_TOPCHILD     4

#define WIN_NULLLINK    -1

enum pw_batch_type {
		PW_NONE =   0x7FFFFFFF,
		PW_ALL  =   0x7FFFFFFE,
		PW_SHOW =   0x7FFFFFFD,
};

struct  pixwin {
		struct  pixrectops *pw_ops;
		caddr_t pw_opshandle;
		int     pw_opsx;
		int     pw_opsy;
		struct  rectlist pw_fixup;
		struct  pixrect *pw_pixrect;
		struct  pixrect *pw_prretained;
		struct  pixwin_clipops *pw_clipops;
		struct  pixwin_clipdata *pw_clipdata;
		char    pw_cmsname[20];
};

struct  pixwin_clipops {
		int     (*pwco_lock)( ... );
		int     (*pwco_unlock)( ... );
		int     (*pwco_reset)( ... );
		int     (*pwco_getclipping)( ... );
};

struct  pixwin_clipdata {
		int     pwcd_windowfd;
		short   pwcd_state;
		struct  rectlist pwcd_clipping;
		int     pwcd_clipid;
		int     pwcd_damagedid;
		int     pwcd_lockcount;
		struct  pixrect *pwcd_prmulti;
		struct  pixrect *pwcd_prsingle;
		struct  pixwin_prlist *pwcd_prl;
		struct  rectlist pwcd_clippingsorted[RECTS_SORTS];
		struct  rect *pwcd_regionrect;
		int     pwcd_x_offset;
		int     pwcd_y_offset;
		int     pwcd_flags;
		caddr_t pwcd_client;
		enum    pw_batch_type pwcd_batch_type;
		int     pwcd_op_count;
		int     pwcd_op_limit;
		struct  rect pwcd_batchrect;
		int             pwcd_winnum;
		struct win_lock_block   *pwcd_wl;
		int     pwcd_screen_x;
		int     pwcd_screen_y;
		char    pwcd_plane_group;
		char    pwcd_plane_groups_available[PIX_MAX_PLANE_GROUPS];
};

struct pw_pixel_cache {
		struct rect r;
		struct pixrect *plane_group[PIX_MAX_PLANE_GROUPS];
};

struct _cursor {
		short   cur_xhot, cur_yhot;
		int     cur_function;
		struct  pixrect *cur_shape;
		int     flags;

		short   horiz_hair_thickness;
		int     horiz_hair_op;
		int     horiz_hair_color;
		short   horiz_hair_length;
		short   horiz_hair_gap;

		short   vert_hair_thickness;
		int     vert_hair_op;
		int     vert_hair_color;
		short   vert_hair_length;
		short   vert_hair_gap;
};

struct inputmask {
		short   im_flags;
		char    im_inputcode[IM_CODEARRAYSIZE];
		short   im_shifts;
		short   im_shiftcodes[IM_SHIFTARRAYSIZE];
};

struct fullscreen_t {
		int     fs_windowfd;
		struct  rect fs_screenrect;
		struct  pixwin *fs_pixwin;
		struct  _cursor fs_cachedcursor;
		struct  inputmask fs_cachedim;
		int     fs_cachedinputnext;
		struct  inputmask fs_cachedkbdim;
};

struct timeval {
		long    tv_sec;         /* seconds */
		long    tv_usec;        /* and microseconds */
};

struct  inputevent {
		short   ie_code;
		short   ie_flags;
		short   ie_shiftmask;
		short   ie_locx, ie_locy;
		struct  timeval ie_time;
};

#define event_id(event)         ((event)->ie_code)
#define event_flags(event)      ((event)->ie_flags)
#define event_shiftmask(event)  ((event)->ie_shiftmask)
#define event_x(event)          ((event)->ie_locx)
#define event_y(event)          ((event)->ie_locy)
#define event_time(event)       ((event)->ie_time)
#define event_shiftmask(event)          ((event)->ie_shiftmask)
#define event_shift_is_down(event)      (event_shiftmask(event) & SHIFTMASK)
#define event_ctrl_is_down(event)       (event_shiftmask(event) & CTRLMASK)
#define event_meta_is_down(event)       (event_shiftmask(event) & META_SHIFT_MASK)

#define pw_rop(dpw, dx, dy, w, h, op, sp, sx, sy)                       \
		(*(dpw)->pw_ops->pro_rop)((dpw)->pw_opshandle,                  \
			(dx)-(dpw)->pw_opsx, (dy)-(dpw)->pw_opsy, (w), (h), (op),   \
			(sp), (sx), (sy))
#define pw_batchrop(dpw, x, y, op, sbp, n)                              \
		(*(dpw)->pw_ops->pro_batchrop)((dpw)->pw_opshandle,             \
			(x)-(dpw)->pw_opsx, (y)-(dpw)->pw_opsy, (op), (sbp), (n))
#define pw_stencil(dpw, x, y, w, h, op, stpr, stx, sty, spr, sy, sx)    \
		(*(dpw)->pw_ops->pro_stencil)((dpw)->pw_opshandle,              \
			x-(dpw)->pw_opsx, y-(dpw)->pw_opsy, (w), (h), (op),         \
			(stpr), (stx), (sty), (spr), (sy), (sx))
#define pw_destroy(pw)                                                  \
		(*pw_opsstd_ptr->pro_destroy)((pw))
#define pw_get(pw, x, y)                                                \
		(*pw_opsstd_ptr->pro_get)((pw),                                 \
			(x)-(pw)->pw_clipdata->pwcd_x_offset,                       \
			(y)-(pw)->pw_clipdata->pwcd_y_offset)
#define pw_put(pw, x, y, val)                                           \
		(*(pw)->pw_ops->pro_put)((pw)->pw_opshandle,                    \
			(x)-(pw)->pw_opsx, (y)-(pw)->pw_opsy, (val))
#define pw_vector(pw, x0, y0, x1, y1, op, val)                          \
		(*(pw)->pw_ops->pro_vector)((pw)->pw_opshandle,                 \
			(x0)-(pw)->pw_opsx, (y0)-(pw)->pw_opsy,                     \
			(x1)-(pw)->pw_opsx, (y1)-(pw)->pw_opsy, (op), (val))
#define pw_region(pw, x, y, w, h)                                       \
		(struct pixwin *)(*pw_opsstd_ptr->pro_region)((pw),             \
			(x), (y), (w), (h))
#define pw_lock(pixwin,rect)                                            \
		(*(pixwin)->pw_clipops->pwco_lock)((pixwin), (rect));
#define pw_unlock(pixwin)                                               \
		(*(pixwin)->pw_clipops->pwco_unlock)((pixwin));
#define pw_read(dpr, dx, dy, w, h, op, spw, sx, sy)                     \
		(*pw_opsstd_ptr->pro_rop)((dpr), (dx), (dy), (w), (h),          \
			(op), (spw), (sx)-(spw)->pw_clipdata->pwcd_x_offset,        \
			(sy)-(spw)->pw_clipdata->pwcd_y_offset)
#define pw_copy(dpw, dx, dy, w, h, op, spw, sx, sy)                     \
		(*pw_opsstd_ptr->pro_rop)((dpw),                                \
			(dx)-(dpw)->pw_clipdata->pwcd_x_offset,                     \
			(dy)-(dpw)->pw_clipdata->pwcd_y_offset, (w), (h), (op),     \
			(spw), (sx)-(spw)->pw_clipdata->pwcd_x_offset,              \
			(sy)-(spw)->pw_clipdata->pwcd_y_offset)
#define pw_putcolormap(pw, index, count, red, green, blue)              \
		(*pw_opsstd_ptr->pro_putcolormap)((pw),                         \
			(index), (count), (red), (green), (blue))


#define pr_rop(dpr, dx, dy, w, h, op, spr, sx, sy)                      \
		(*(dpr)->pr_ops->pro_rop)(dpr, dx, dy, w, h, op, spr, sx, sy)
#define pr_batchrop(dpr, x, y, op, sbp, n)                              \
		(*(dpr)->pr_ops->pro_batchrop)(dpr, x, y, op, sbp, n)
#define pr_stencil(dpr, dx, dy, w, h, op, stpr, stx, sty, spr, sx, sy)  \
		(*(dpr)->pr_ops->pro_stencil)(dpr,dx,dy,w,h,op,stpr,stx,sty,spr,sx,sy)
#define pr_destroy(pr)                                                  \
		(*(pr)->pr_ops->pro_destroy)(pr)
#define pr_close(pr)    pr_destroy(pr)
#define pr_get(pr, x, y)                                                \
		(*(pr)->pr_ops->pro_get)(pr, x, y)
#define pr_put(pr, x, y, val)                                           \
		(*(pr)->pr_ops->pro_put)(pr, x, y, val)
#define pr_vector(pr, x0, y0, x1, y1, op, color)                        \
		(*(pr)->pr_ops->pro_vector)(pr, x0, y0, x1, y1, op, color)
#define pr_region(pr, x, y, w, h)                                       \
		(*(pr)->pr_ops->pro_region)(pr, x, y, w, h)

#define PIX_SRC         (0xC << 1)
#define PIX_DST         (0xA << 1)
#define PIX_NOT(op)     ((op) ^ 0x1E)
#define PIX_CLR         (0x0 << 1)
#define PIX_SET         (0xF << 1)
#define PIX_ERASE       (PIX_NOT(PIX_SRC) & PIX_DST)

#define PIX_DONTCLIP    0x1

#define PIX_OR          (PIX_SRC | PIX_DST)

#define PIX_COLOR(c)    ((c)<<5)

extern "C" {
	void rect_intersection(struct rect*, struct rect*, struct rect*);
	rect rect_bounding(rect *r1, rect *r2);

	void rl_copy(rectlist *r1, rectlist *rld);
	void rl_intersection(rectlist *r1, rectlist *r2, rectlist *rld);
	void rl_coalesce(rectlist *);
	void rl_sort(rectlist*,rectlist*, int);
	void rl_normalize(rectlist*);
	void rl_free(rectlist*);

	struct pixrect *mem_create(int, int, int);
	struct pixrect *mem_point(int, int, int, short*);

	extern struct pixrect *pr_load(FILE*, colormap_t*);
	extern int pr_load_colormap(FILE*, struct rasterfile*, colormap_t*);
	extern int pr_load_header(FILE*, struct rasterfile*);
	extern struct pixrect *pr_load_image(FILE*, struct rasterfile*, colormap_t*);
	extern struct pixrect *pr_load_std_image(FILE*, struct rasterfile*, colormap_t*);
	extern void pr_replrop(pixrect*, int xw, int yw,
								int width, int height, int op,
								pixrect*, int xr, int yr);
	extern void pr_polygon_2(pixrect*,int,int,int,int*,struct pr_pos*,int,pixrect*,int,int);
	extern void pr_traprop(pixrect*,int,int,struct pr_trap,int,pixrect*,int,int);
	extern void pr_polypoint(pixrect*,int,int,int,struct pr_pos *,int);

	struct pixfont *pf_open(char*);
	struct pixfont *pf_open_private(char*);
	struct pixfont *pf_default();
	void pf_close(struct pixfont*);

}

extern "C" {

	extern pixwin *pw_open(int);
	extern void pw_polygon_2(pixwin*,int,int,int,int*,pr_pos*,int,pixrect*,int,int);
	extern int pw_set_region_rect(pixwin*, rect*, u_int, u_int);
	extern void pw_set_xy_offset(pixwin*, int xoff, int yoff);
	extern void pw_replrop(pixwin*, int xw, int yw,
								int width, int height, int op,
								struct pixrect *, int xr, int yr);

	extern void pw_traprop(pixwin*,int,int,struct pr_trap,int,pixrect*,int,int);
	extern void pw_polypoint(pixwin*,int,int,int,struct pr_pos *,int);
	extern void pw_close(pixwin*);
	extern void pw_damaged(pixwin*);
	extern void pw_donedamaged(pixwin*);
	extern void pw_setcmsname(pixwin*, char*);
	extern void pw_exposed(pixwin *pw);
	extern void fullscreen_pw_copy(pixwin*, int x, int y, int w, int h, int op,
											pixwin*, int x, int y);

	pw_pixel_cache *pw_save_pixels(pixwin*, struct rect *r);
	void pw_restore_pixels(pixwin*, pw_pixel_cache*);

	extern int win_getnewwindow();      // misc, misc.data
	extern void win_getrect(int fd, struct rect*);
	extern void win_setrect(int fd, struct rect*);
	extern void win_grabio(int);
	extern void win_releaseio(int);
	extern void win_remove(int);
	extern int win_nametonumber(const char*);
	extern int win_getlink(int fd, int linkname);
	extern void win_setlink(int fd, int linkname, int number);
	extern void win_insert(int fd);
	extern void win_computeclipping(int wfd);
	extern void win_lockdata(int wfd);
	extern void win_unlockdata(int wfd);
	extern void win_partialrepair(int wfd, struct rect*);
	extern int win_findintersect(int fd, int x, int y);
	extern int win_fdtonumber(int fd);
	extern int win_getuserflags(int fd);
	extern int win_setuserflag(int fd, int flag, int val);
	extern int win_numbertoname(int fd, char *name);

#   define win_inputnegevent(ie)   ((ie)->ie_flags&IE_NEGEVENT)

	extern struct fullscreen_t *fullscreen_init(int windowfd);
	extern void fullscreen_destroy(struct fullscreen_t *fs);

	extern int input_readevent(int fd, inputevent *ie);

	extern void _sunwindow_setmouse(int fd, int, int, bool);
	extern void _sunwindow_setmask(int fd);
	extern void _sunwindow_setcursor(int fd, struct _cursor *);
	extern void _sunwindow_bell(int fd, long duration);
	extern int _sunwindow_ttychars(char&, char&);
}

extern struct pixrectops *pw_opsstd_ptr;

#endif

